/*
 * Copyright (c) 2009-2010 jMonkeyEngine
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 * * Redistributions of source code must retain the above copyright
 *   notice, this list of conditions and the following disclaimer.
 *
 * * Redistributions in binary form must reproduce the above copyright
 *   notice, this list of conditions and the following disclaimer in the
 *   documentation and/or other materials provided with the distribution.
 *
 * * Neither the name of 'jMonkeyEngine' nor the names of its contributors
 *   may be used to endorse or promote products derived from this software
 *   without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

package com.colladaviewer.app;

import android.view.MotionEvent;
import android.app.Activity;
import android.hardware.Camera;

import com.colladaviewer.android.camera.AndroidARManager;
import com.jme3.font.BitmapText;
import com.jme3.input.android.AndroidInput;
import com.jme3.input.android.TouchEvent;
import com.jme3.app.SimpleApplication;
import com.jme3.asset.AssetManager;
import com.jme3.asset.TextureKey;
import com.jme3.asset.plugins.AndroidLocator;
import com.jme3.asset.plugins.AndroidZipLocator;
import com.jme3.asset.plugins.HttpZipLocator;
import com.jme3.asset.plugins.ZipLocator;
import com.jme3.bounding.BoundingBox;
import com.jme3.bounding.BoundingVolume;
import com.jme3.input.android.AndroidTouchInputListener;
import com.jme3.input.event.JoyAxisEvent;
import com.jme3.input.event.JoyButtonEvent;
import com.jme3.input.event.KeyInputEvent;
import com.jme3.input.event.MouseButtonEvent;
import com.jme3.input.event.MouseMotionEvent;
import com.jme3.light.AmbientLight;
import com.jme3.light.DirectionalLight;
import com.jme3.light.PointLight;
import com.jme3.material.Material;
import com.jme3.material.RenderState.BlendMode;
import com.jme3.math.ColorRGBA;
import com.jme3.math.FastMath;
import com.jme3.math.Matrix3f;
import com.jme3.math.Matrix4f;
import com.jme3.math.Quaternion;
import com.jme3.math.Vector2f;
import com.jme3.math.Vector3f;
import com.jme3.renderer.ViewPort;
import com.jme3.renderer.queue.RenderQueue;
import com.jme3.renderer.queue.RenderQueue.Bucket;
import com.jme3.renderer.queue.RenderQueue.ShadowMode;
import com.jme3.scene.Geometry;
import com.jme3.scene.Node;
import com.jme3.scene.Spatial;
import com.jme3.scene.Spatial.CullHint;
import com.jme3.scene.shape.Cylinder;
import com.jme3.scene.shape.Quad;
import com.jme3.scene.shape.Sphere;
import com.jme3.scene.shape.Torus;
import com.jme3.system.AppSettings;
import com.jme3.system.JmeSystem;
import com.jme3.texture.Image;
import com.jme3.texture.Texture;
import com.jme3.util.SkyFactory;
import com.neotank.app.AndroidApplication;
import com.neotank.input.VirtualJoystick;
import com.neotank.texture.MaterialAutoLoader;

import java.io.File;
import java.util.logging.Level;
import java.util.logging.Logger;

import jme3dae.ColladaLoader;

public class ARScene extends AndroidApplication {
    
    private Camera device = null;
    
    private final static float rotationSpeed = 0.6f;
    private final static float moveSpeed = 8.0f;
    private Vector3f initialUpVec;
    
    private final static Logger logger = Logger.getLogger(ARScene.class.getName());
    
    private Sphere sphereMesh = new Sphere(32, 32, 100, false, true);
    private Geometry sphere = new Geometry("Sky", sphereMesh);
    Node backGroundNode;
    Spatial scene;
    
    private float posX;
    private float posY;
    
    float angle;
    PointLight pl;
    Geometry lightMdl;
    BitmapText infoText;
    
    DirectionalLight sun;
    
    Texture image;
    AndroidARManager armanager;
    Material mat;
    Matrix4f markerMatrix;
    Vector3f translation = new Vector3f();
    Quaternion rotation = new Quaternion();
    float[] angles = new float[3]; 
    
    int iNotDetecedCounter = 0;
        
    public static void main(String[] args) {

        ARScene app = new ARScene();
        app.start();
    }

    public ARScene() 
    {
        super();
    }
    
    public ARScene(Activity activity, AndroidInput input) 
    {
        super(activity, input);
        armanager = AndroidARManager.get(activity, input.getHolder());
    }
    
    @Override
    public void update(float tpf)
    {
        backGroundNode.updateLogicalState(tpf);
        backGroundNode.updateGeometricState();  
  

        if (armanager != null)
        {
            if (armanager.getException() == null)
            {
                image = armanager.getTexture();    
                if (image != null)
                {
                    mat.setTexture("ColorMap", image);
                }
                if (armanager.applyDetectedMatrix(scene))
                {
                    infoText.setText("Detected 1");
                    sun.setColor(ColorRGBA.White.clone().multLocal(2f));
                    iNotDetecedCounter = 0;
                }
                else
                {
                    iNotDetecedCounter++;
                    infoText.setText("Detected 0");
                    if (iNotDetecedCounter > 5)
                    {
                        sun.setColor(ColorRGBA.White.clone().multLocal(0.1f));
                    }
                }
            }
            else
            {
                handleError("ARManager failed", armanager.getException());
                this.stop();
            }
            

        }
    }

    public void simpleInitApp() {
        
        initialUpVec = cam.getUp().clone();

        this.cam.setLocation(new Vector3f(0f, 0f, 0f));
       
        assetManager.registerLoader(ColladaLoader.class, "dae");
        scene = assetManager.loadModel("Models/Female.dae");
        
        BoundingBox bb = (BoundingBox)scene.getWorldBound();        
        float maxExtent = Math.max(bb.getXExtent(), bb.getZExtent());
        scene.scale(1f/(maxExtent*4));        
        
        MaterialAutoLoader.OptimizeAllMaterials(scene, assetManager); 
        rootNode.attachChild(scene);
        
        

        AmbientLight al = new AmbientLight();
        al.setColor(ColorRGBA.LightGray.multLocal(1f));
        rootNode.addLight(al);

        sun = new DirectionalLight();
        sun.setDirection(new Vector3f(0.69077975f, -0.6277887f, -0.35875428f).normalizeLocal());
        sun.setColor(ColorRGBA.White.clone().multLocal(1f));
        scene.addLight(sun);
        

               
        Quad q = new Quad(input.getWidth(), input.getHeight());               
        Geometry geom = new Geometry("PREVIEW_BACKGROUND", q);        
        geom.setQueueBucket(Bucket.Gui);        
        geom.setCullHint(CullHint.Never);
        
        // bottom left
        Vector3f loc = new Vector3f(0f,0f,-2.0f);
        geom.setLocalTranslation(loc);

        mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
        mat.setColor("Color", new ColorRGBA(0.5f,0.5f,1f,1f));
        Texture textureMonkey = assetManager.loadTexture(new TextureKey("Interface/Logo/Monkey.jpg"));
        mat.setTexture("ColorMap", textureMonkey);
        geom.setMaterial(mat);
        
        backGroundNode = new Node();
        backGroundNode.setCullHint(CullHint.Never);
        backGroundNode.setQueueBucket(Bucket.Gui);
        backGroundNode.attachChild(geom);
                        
        ViewPort backgroundView = renderManager.createPreView("BACKGROUND_VIEW", cam);               
        backgroundView.attachScene(backGroundNode);
        backgroundView.setEnabled(true);        
        backgroundView.setClearColor(true);
        
        viewPort.setClearColor(false);
        
        
        //guiNode.attachChild(geom);
                


        infoText = new BitmapText(guiFont, false);
        infoText.setLocalTranslation(0, infoText.getLineHeight()*2.1f, 0);
        infoText.setText("Detected 0");        
        guiNode.attachChild(infoText);
        
        //cam.setProjectionMatrix(armanager.getProjectionMatrix());
        //cam.lookAt(scene.getLocalTranslation(), Vector3f.UNIT_Y);
        //cam.update();
        //cam.updateViewProjection();
        
        rootNode.setShadowMode(RenderQueue.ShadowMode.Off);
        guiNode.setShadowMode(RenderQueue.ShadowMode.Off); 
    }
    
    void rotateCamera(float value, float tpf, Vector3f axis)
    {
        Matrix3f mat = new Matrix3f();
        mat.fromAngleNormalAxis(-1f * rotationSpeed * value * tpf, axis);

        Vector3f up = cam.getUp();
        Vector3f left = cam.getLeft();
        Vector3f dir = cam.getDirection();

        mat.mult(up, up);
        mat.mult(left, left);
        mat.mult(dir, dir);

        Quaternion q = new Quaternion();
        q.fromAxes(left, up, dir);
        q.normalize();

        cam.setAxes(q);
    }
    
    /**
     * Move the cam forward by value
     * @param value
     */
    protected void moveCamera(float value, float tpf)
    {
        Vector3f vel = new Vector3f();
        Vector3f pos = cam.getLocation().clone();
        cam.getDirection(vel);
    
        vel.multLocal(value * moveSpeed * tpf);
    
        pos.addLocal(vel);    
        cam.setLocation(pos);
    }
      

}
